{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "4b34863c-57ca-4ef6-8d3e-b62bbf6e2594",
   "metadata": {},
   "source": [
    "## 文档切割\n",
    "\n",
    "### 原理\n",
    "1. 将文档分成小的、有意义的块(句子)\n",
    "2. 将小的块组合成一个更大的块,直到达到一定的大小。\n",
    "3. 一旦达到一定的大小,接着开始创建与下一个块重叠的部分\n",
    "\n",
    "### 示例\n",
    "第一个文档分割\n",
    "- 按字符切割\n",
    "- 代码文档切割\n",
    "- 按token来切割"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "852f0ee9-c73b-4f8b-b6e8-7efbd0080583",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Document(metadata={'start_index': 6}, page_content='蒂法·洛克哈特(日语:ティファ・ロックハート，Tifa Rokkuhāto，英语:Tifa')"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from langchain.text_splitter import RecursiveCharacterTextSplitter\n",
    "\n",
    "#加载要切分的文档\n",
    "with open(\"test.txt\", encoding='utf-8') as f:\n",
    "    zuizhonghuanxiang = f.read()\n",
    "\n",
    "#使用递归字符切分器\n",
    "text_splitter = RecursiveCharacterTextSplitter(\n",
    "    chunk_size=50,#切分的文本块大小,一般通过长度函数计算\n",
    "    chunk_overlap=20,#切分的文本块重叠大小,一般通过长度函数计算\n",
    "    length_function=len,#长度函数,也可以传递tokenize函数\n",
    "    add_start_index=True,#是否添加开始索引\n",
    ")\n",
    "\n",
    "text = text_splitter.create_documents([zuizhonghuanxiang])\n",
    "text[0]\n",
    "text[1]\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "1771a9ce-9a5c-40e1-ba61-4fe2a11672a8",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Document(metadata={'start_index': 199}, page_content='在米德加经营作为反抗组织“雪崩”根 据地的酒馆“第七天堂”，并且是小有名气的招牌店员。擅⻓格斗，以拳套为武器。本传7年前 克劳德离开故乡从军时，曾许下约定“如果有危机时一定会保护她”。与爱丽丝相识之后，两 人成为好友。第一个察觉克劳德记忆混乱的人，后来协助精神崩溃的克劳德\\U0010fc01新找回真正的自 己')"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from langchain.text_splitter import CharacterTextSplitter\n",
    "\n",
    "#加载要切分的文档\n",
    "with open(\"test.txt\", encoding='utf-8') as f:\n",
    "    zuizhonghuanxiang = f.read()\n",
    "\n",
    "#按字符切割\n",
    "text_splitter = CharacterTextSplitter(\n",
    "    separator=\"。\", #分隔符，默认\\n\n",
    "    chunk_size=200,#切分的文本块大小,一般通过长度函数计算\n",
    "    chunk_overlap=20,#切分的文本块重叠大小,一般通过长度函数计算\n",
    "    length_function=len,#长度函数,也可以传递tokenize函数\n",
    "    add_start_index=True,#是否添加开始索引\n",
    "    is_separator_regex=False # 是否使用正则\n",
    ")\n",
    "\n",
    "text = text_splitter.create_documents([zuizhonghuanxiang])\n",
    "text[0]\n",
    "text[1]\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "c3ffd938-3018-485d-afd5-72585ca53b4a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[Document(metadata={}, page_content='def hello_world():\\n    print(\"Hello, World!\")'),\n",
       " Document(metadata={}, page_content='#调用函数\\nhello_world()')]"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from langchain.text_splitter import (\n",
    "    RecursiveCharacterTextSplitter,\n",
    "    Language,\n",
    ")\n",
    "\n",
    "#支持解析的编程语言\n",
    "#[e.value for e in Language]\n",
    "\n",
    "#要切割的代码文档\n",
    "PYTHON_CODE = \"\"\"\n",
    "def hello_world():\n",
    "    print(\"Hello, World!\")\n",
    "#调用函数\n",
    "hello_world()\n",
    "\"\"\"\n",
    "\n",
    "# 按代码分割\n",
    "py_spliter = RecursiveCharacterTextSplitter.from_language(\n",
    "    language=Language.PYTHON, # 指定编程语言\n",
    "    chunk_size=50,\n",
    "    chunk_overlap=10,\n",
    ")\n",
    "python_docs = py_spliter.create_documents([PYTHON_CODE])\n",
    "python_docs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "2f726100-81ba-4b7f-95db-eea7096a533e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "page_content='蒂法介绍\n",
      "蒂法·洛克哈特(日语:ティファ・ロックハート，Tifa Rokkuhāto，英语:Tifa Lockhart)为电子游戏《最终幻想VII》及《最终幻想VII补完计划》相关作品中的虚构⻆ 色，由􏰀村哲也创作和设计，此后也在多个游戏中客串登场。 2014年东京电玩展上，星名美津纪cosplay《最终幻想VII 降临之子》中的蒂法·洛克哈特 蒂法是克劳德的⻘梅竹⻢，两人同为尼布鲁海姆出身。在米德加经营作为反抗组织“雪崩”根 据地的酒馆“第七天堂”，并且是小有名气的招牌店员。擅⻓格斗，以拳套为武器。本传7年前 克劳德离开故乡从军时，曾许下约定“如果有危机时一定会保护她”。与爱丽丝相识之后，两 人成为好友。第一个察觉克劳德记忆混乱的人，后来协助精神崩溃的克劳德􏰁新找回真正的自 己。本传的大战结束后，依大家的期待在战后新生的米德加再次开设第七天堂(原第七天堂因 第柒区圆盘崩塌遭压毁)，同时也照顾一群受到星痕症候群折磨的孩子们。 蒂法被《纽约时报》称为“网络一代”的海报女郎，与劳拉·克罗夫特相比，她是电子游戏中坚 强、􏰂立和有吸引力的女性⻆色的典型代表。媒体普遍称赞其实力和外表，并称她为游戏世界 中最好的女性⻆色之一。 在《最终幻想VII》本传中，蒂法年龄20岁、身高167cm、生日5月3日、血型B型、出生地尼 布尔海姆。\n",
      "登场\n",
      "《最终幻想VII》 蒂法在《最终幻想VII》原版中首次亮相，是克劳德的⻘梅竹⻢、第七天堂酒吧的看板娘、极 端环境组织“雪崩”成员，该组织反抗巨型企业“神罗”因其大􏰃抽取魔晄用作动力能源。在注 意到克劳德的性格改变后，她说服克劳德加入雪崩，以密切关注他，并且跟随他追寻游戏中的 对手萨菲罗斯。她无法阻止克劳德被萨菲罗斯操纵，在他的精神崩溃后，她帮助克劳德康复， 并且两人意识到彼此间的相互感觉，最后与伙伴们一同击败了萨菲罗斯。[2] 在闪回中可知，儿时的蒂法一直是村中小孩的人气王。在母亲过世后，思念母亲的蒂法决定沿 着小路走到他们故乡尼布尔海姆附近的一座山上，认为这样就能⻅到过世的母亲，原本跟着蒂 法的其他小孩都在半路上因害怕而放弃，唯􏰂克劳德仍坚定的在后面跟随，希望能在危机时保 护蒂法。然而，他们俩都从山上跌落受伤，蒂法昏迷了一个星期，她的父亲认为克劳德对此负 有责任[3]，甚为严令禁止克劳德再接近蒂法，但蒂法反而从此更在意克劳德，两人成为要好 的玩伴。为了使自己变得更强大，克劳德最终选择离开尼布尔海姆，加入神罗，想要成为神罗 的精英战士“神罗战士”(SOLDIER)，但后来透露他主要是为了吸引蒂法的注意力。离开之 前，蒂法与克劳德约定，当蒂法处于困境之中时，克劳德会回来救她。从克劳德离开之后，蒂 法便开始留意神罗战士的消息，因为神罗战士都成为声名远播的知名人物，如果克劳德成为神 罗战士，他的活跃也会立刻传回尼布尔海姆。数年后，在萨菲罗斯摧毁了尼布尔海姆之后，克 劳德为了救蒂法，被萨菲罗斯刺至􏰁伤。蒂法被她的武术教练赞干带到安全地带，幸存下来， 最终到达米德加并遇⻅了“雪崩”的领导人巴雷特·华莱士。病愈后，蒂法加入了“雪崩”，为 了给家乡被毁一事报仇。一天，她在火⻋站遇到了从魔晄炉中逃出来、精神一片混乱的克劳 德，蒂法说服了他为巴雷特工作，以保证克劳德的安全以及和克劳德保持紧密关系。这是游戏 开始的地方。 在原版《最终幻想VII》中蒂法与爱丽丝关系友好，但会在某些时候争⻛吃醋，例如在神罗总 部营救爱丽丝时，蒂法及巴雷特等一行失手被擒，若克劳德选择关心爱丽丝的话蒂法的对话中 明显带有妒忌。在􏰁制版中虽然删去这段情节，但保留了这种关系。 在《最终幻想VII》的初稿中，蒂法是背景人物。她在“雪崩”中的作用是在幕后支持，在执 行任务后为所有人加油鼓劲，并且对克劳德有特别的关心。据推测，她的背上有一块大的疤'\n"
     ]
    }
   ],
   "source": [
    "from langchain.text_splitter import CharacterTextSplitter\n",
    "\n",
    "#要切割的文档\n",
    "with open(\"test.txt\", encoding='utf-8') as f:\n",
    "    zuizhonghuanxiang = f.read()\n",
    "\n",
    "#按token分割\n",
    "text_splitter = CharacterTextSplitter.from_tiktoken_encoder(\n",
    "    chunk_size=4000,#切分的文本块大小，一般通过长度函数计算\n",
    "    chunk_overlap=30,#切分的文本块重叠大小，一般通过长度函数计算\n",
    ")\n",
    "\n",
    "text = text_splitter.create_documents([zuizhonghuanxiang])\n",
    "print(text[0])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e4139407-60bc-443d-b8c7-4e740205ba85",
   "metadata": {},
   "source": [
    "### 文档的总结、精炼和翻译"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "eeea4dc3-ce07-4606-9d72-67f523af929e",
   "metadata": {},
   "outputs": [],
   "source": [
    "! pip install doctran"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "156878e5-2f15-4c64-8d14-d9bd937389f0",
   "metadata": {},
   "outputs": [],
   "source": [
    "from dotenv import load_dotenv\n",
    "\n",
    "import os\n",
    "load_dotenv(\"openai.env\", encoding=\"utf-8\")\n",
    "OPENAI_API_KEY = os.environ.get(\"OPEN_API_KEY\")\n",
    "OPENAI_API_BASE = os.environ.get(\"OPENAI_API_BASE\")\n",
    "OPENAI_MODEL = \"gpt-3.5-turbo-16k\"\n",
    "OPENAI_TOKEN_LIMIT = 8000\n",
    "\n",
    "# 加载文档\n",
    "with open(\"letter.txt\", encoding='utf-8') as f:\n",
    "    content = f.read()\n",
    "\n",
    "from doctran import Doctran\n",
    "doctrans = Doctran(\n",
    "    openai_api_key=OPENAI_API_KEY,\n",
    "    openai_model=OPENAI_MODEL,\n",
    "    openai_token_limit=OPENAI_TOKEN_LIMIT,\n",
    ")\n",
    "\n",
    "documents = doctrans.parse(content=content)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5ede01f6-ed05-4e21-8562-3398fc709bf9",
   "metadata": {},
   "outputs": [],
   "source": [
    "#总结文档\n",
    "summary = documents.summarize(token_limit=100).execute() # 总结限制在100token\n",
    "print(summary.transformed_content)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d76112f9-8d65-4c5a-ab9d-389403f63da3",
   "metadata": {},
   "outputs": [],
   "source": [
    "#翻译一下文档\n",
    "translation = documents.translate(language=\"chinese\").execute()\n",
    "print(translation.transformed_content)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c933db73-53f2-481f-940d-f42c20a4f415",
   "metadata": {},
   "outputs": [],
   "source": [
    "#精炼文档，删除除了某个主题或关键词之外的内容，仅保留与主题相关的内容\n",
    "refined = documents.refine(topics=[\"marketing\",\"Development\"]).execute()\n",
    "print(refined.transformed_content)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2a8fc0b1-08cc-4491-a73d-3fc1a81bc9f3",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python (langchain)",
   "language": "python",
   "name": "langchain-env"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.13.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
